package com.atguigu.gmall.product.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.cache.GmallCache;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.model.product.*;
import com.atguigu.gmall.product.mapper.BaseCategoryViewMapper;
import com.atguigu.gmall.product.mapper.BaseTrademarkMapper;
import com.atguigu.gmall.product.mapper.SkuImageMapper;
import com.atguigu.gmall.product.mapper.SkuInfoMapper;
import com.atguigu.gmall.product.service.ApiSkuInfoService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class ApiSkuInfoServiceImpl implements ApiSkuInfoService {

    @Autowired
    private SkuInfoMapper skuInfoMapper;

    @Autowired
    private SkuImageMapper skuImageMapper;

    @Autowired
    private BaseCategoryViewMapper baseCategoryViewMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private BaseTrademarkMapper baseTrademarkMapper;

    /**
     * 根据skuid获取sku详情数据
     * @param skuId
     * @return
     */
    @Override
    @GmallCache(prefix = "skuInfo:")
    public SkuInfo getAttrValueList(Long skuId) {

        SkuInfo skuInfo;
        skuInfo = skuInfoMapper.selectById(skuId);
        QueryWrapper<SkuImage> skuImageQueryWrapper = new QueryWrapper<>();
        skuImageQueryWrapper.eq("sku_id",skuId);
        List<SkuImage> skuImages = skuImageMapper.selectList(skuImageQueryWrapper);
        skuInfo.setSkuImageList(skuImages);
        return skuInfo;
    }

//    private SkuInfo getSkuInfoB2(Long skuId) {
//        try {
//            // 先查看缓存中有没有数据，如果有，则直接返回数据，没有的话则查询数据库
//            String skuKey = RedisConst.SKUKEY_PREFIX+skuId+RedisConst.SKUKEY_SUFFIX;
//            SkuInfo skuInfo = (SkuInfo) redisTemplate.opsForValue().get(skuKey);
//            if (skuInfo == null){
//
//                //使用redisson来实现分布式锁
//                String lockKey = RedisConst.SKUKEY_PREFIX+skuId+RedisConst.SKULOCK_SUFFIX;
//                RLock lock = redissonClient.getLock(lockKey);
//                boolean isExist = lock.tryLock(RedisConst.SKULOCK_EXPIRE_PX1, RedisConst.SKULOCK_EXPIRE_PX2, TimeUnit.SECONDS);
//
//                if (isExist){// 如果为true 则上锁成功
//                    try {
//                        skuInfo = skuInfoMapper.selectById(skuId);
//                        //如果查询出来的对象是空的，则将一个null值放入到缓存中
//                        if (skuInfo == null){
//                            //将null放入到缓存中
//                            SkuInfo skuInfo1 = new SkuInfo();
//                            // 将一个空对象放入到缓存中
//                            redisTemplate.opsForValue().set(skuKey,skuInfo1,RedisConst.SKUKEY_TEMPORARY_TIMEOUT, TimeUnit.SECONDS);
//
//                            return skuInfo1;
//                        }
//                        // 查询图片信息
//                        QueryWrapper<SkuImage> skuImageQueryWrapper = new QueryWrapper<>();
//                        skuImageQueryWrapper.eq("sku_id",skuId);
//                        List<SkuImage> skuImages = skuImageMapper.selectList(skuImageQueryWrapper);
//                        skuInfo.setSkuImageList(skuImages);
//                        // 如果不为空的话，则将查询到的对象放入到缓存中
//                        redisTemplate.opsForValue().set(skuKey,skuInfo,RedisConst.SKUKEY_TIMEOUT, TimeUnit.SECONDS);
//
//
//                        return skuInfo;
//                    } finally {
//                        lock.unlock();
//                    }
//
//                }else{
//                    try {
//                        Thread.sleep(2000);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//                    return getAttrValueList(skuId);
//                }
//            }else{
//                return skuInfo;
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//
//        // 查询图片信息
//        return getSkuInfoNew(skuId);
//    }
//
//    private SkuInfo getSkuInfoRedis01(Long skuId) {
//        try {
//            // 先查看缓存中有没有数据，如果有，则直接返回数据，没有的话则查询数据库
//            String skuKey = RedisConst.SKUKEY_PREFIX+skuId+RedisConst.SKUKEY_SUFFIX;
//            SkuInfo skuInfo = (SkuInfo) redisTemplate.opsForValue().get(skuKey);
//            if (skuInfo == null){
//
//                // 如果数据为空，要查询数据库，这里避免缓存穿透问题，使用redis上锁
//                // 创建锁的key
//                String lockKey = RedisConst.SKUKEY_PREFIX+skuId+RedisConst.SKULOCK_SUFFIX;
//                String lockKeyValue = UUID.randomUUID().toString();
//                //开始上锁
//                Boolean isExist = redisTemplate.opsForValue().setIfAbsent(lockKey, lockKeyValue, RedisConst.SKULOCK_EXPIRE_PX2, TimeUnit.SECONDS);
//                if (isExist){// 如果为true 则上锁成功
//                    skuInfo = skuInfoMapper.selectById(skuId);
//                    //如果查询出来的对象是空的，则将一个null值放入到缓存中
//                    if (skuInfo == null){
//                        //将null放入到缓存中
//                        SkuInfo skuInfo1 = new SkuInfo();
//                        // 将一个空对象放入到缓存中
//                        redisTemplate.opsForValue().set(skuKey,skuInfo1,RedisConst.SKUKEY_TEMPORARY_TIMEOUT, TimeUnit.SECONDS);
//
//                        return skuInfo1;
//                    }
//                        // 查询图片信息
//                    QueryWrapper<SkuImage> skuImageQueryWrapper = new QueryWrapper<>();
//                    skuImageQueryWrapper.eq("sku_id",skuId);
//                    List<SkuImage> skuImages = skuImageMapper.selectList(skuImageQueryWrapper);
//                    skuInfo.setSkuImageList(skuImages);
//                    // 如果不为空的话，则将查询到的对象放入到缓存中
//                    redisTemplate.opsForValue().set(skuKey,skuInfo,RedisConst.SKUKEY_TIMEOUT, TimeUnit.SECONDS);
//
//                    // 释放锁
//                    String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
//                    // 设置lua脚本返回的数据类型
//                    DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
//                    // 设置lua脚本返回类型为Long
//                    redisScript.setResultType(Long.class);
//                    redisScript.setScriptText(script);
//                    // 删除key 所对应的 value
//                    redisTemplate.execute(redisScript, Arrays.asList(lockKey),lockKeyValue);
//
//                    return skuInfo;
//
//
//
//                }else{
//                    try {
//                        Thread.sleep(2000);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//                    return getAttrValueList(skuId);
//                }
//            }else{
//                return skuInfo;
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//
//        // 查询图片信息
//        return getSkuInfoNew(skuId);
//    }


    /**
     * 根据skuid获取sku最新价格
     * @param skuId
     * @return
     */
    @Override
    public BigDecimal getSkuPrice(Long skuId) {

        QueryWrapper<SkuInfo> skuInfoQueryWrapper = new QueryWrapper<>();
        skuInfoQueryWrapper.select("price");
        skuInfoQueryWrapper.eq("id",skuId);

        SkuInfo skuInfo = skuInfoMapper.selectOne(skuInfoQueryWrapper);

        return skuInfo.getPrice();
    }

    /**
     * 查询商品的分类信息
     * @param category3Id
     * @return
     */
    @Override
    @GmallCache(prefix = "baseCategoryView:")
    public BaseCategoryView getCategoryView(Long category3Id) {
        QueryWrapper<BaseCategoryView> baseCategoryViewQueryWrapper = new QueryWrapper<>();
        baseCategoryViewQueryWrapper.eq("category3_id",category3Id);
        return baseCategoryViewMapper.selectOne(baseCategoryViewQueryWrapper);
    }

    /**
     * 商品的切换
     * @param spuId
     * @return
     */
    @Override
    @GmallCache(prefix = "skuValueIds:")
    public Map getSkuValueIdsMap(Long spuId) {
        Map<Object,Object> map = new HashMap<>();

        List<Map> mp = skuInfoMapper.selectSkuValueIdsMap(spuId);

        if (mp != null && mp.size() > 0){
            for (Map map1 : mp) {
                map.put(map1.get("value_ids"),map1.get("sku_id"));
            }
        }

        return map;
    }

    // sku对应的平台属性，也就是规格
    @Override
    @GmallCache(prefix = "AttrList:")
    public List<BaseAttrInfo> getAttrList(Long skuId) {
        return skuInfoMapper.selectAttrList(skuId);
    }

    @Override
    @GmallCache(prefix = "getBaseCategoryList:")
    public List<JSONObject> getBaseCategoryList() {
        //  声明集合
        List<JSONObject> list = new ArrayList<>();
        //  调用mapper 查询所有的数据！
        List<BaseCategoryView> categoryViewList = baseCategoryViewMapper.selectList(null);
        //  先声明一个变量
        int index = 1;
        //  以一级分类Id 为 key=category1Id ，一级分类Id 对应的集合数据为value = List<BaseCategoryView> ！
        Map<Long, List<BaseCategoryView>> category1Map = categoryViewList.stream().collect(Collectors.groupingBy(BaseCategoryView::getCategory1Id));
        //  获取到迭代器
        Iterator<Map.Entry<Long, List<BaseCategoryView>>> iterator = category1Map.entrySet().iterator();
        while (iterator.hasNext()){
            Map.Entry<Long, List<BaseCategoryView>> entry = iterator.next();
            //  获取到key
            Long category1Id = entry.getKey();
            //  获取到value
            List<BaseCategoryView> categoryViewList1 = entry.getValue();
            //  创建一个JSONObject 对象 一级分类对象
            JSONObject category1 = new JSONObject();
            category1.put("index",index);
            category1.put("categoryId",category1Id);
            category1.put("categoryName",categoryViewList1.get(0).getCategory1Name());

            //  index 迭代！
            index++;
            //  创建一个二级分类数据集合对象
            List<JSONObject> categoryChild2 = new ArrayList<>();
            //  获取二级分类数据！ key = category2Id value = List<BaseCategoryView>
            Map<Long, List<BaseCategoryView>> category2Map = categoryViewList1.stream().collect(Collectors.groupingBy(BaseCategoryView::getCategory2Id));
            Iterator<Map.Entry<Long, List<BaseCategoryView>>> iterator1 = category2Map.entrySet().iterator();
            while (iterator1.hasNext()){
                Map.Entry<Long, List<BaseCategoryView>> entry1 = iterator1.next();
                Long category2Id = entry1.getKey();
                List<BaseCategoryView> categoryViewList2 = entry1.getValue();
                //  创建一个JSONObject 对象 二级分类对象
                JSONObject category2 = new JSONObject();
                category2.put("categoryId",category2Id);
                category2.put("categoryName",categoryViewList2.get(0).getCategory2Name());

                //  将二级分类数据添加到集合！
                categoryChild2.add(category2);

                //  获取三级分类数据：
                //  创建一个三级分类数据集合对象
                List<JSONObject> categoryChild3 = new ArrayList<>();
                categoryViewList2.forEach(baseCategoryView -> {
                    //  创建一个JSONObject 对象 三级分类对象
                    JSONObject category3 = new JSONObject();
                    category3.put("categoryId",baseCategoryView.getCategory3Id());
                    category3.put("categoryName",baseCategoryView.getCategory3Name());
                    categoryChild3.add(category3);
                });
                //  将三级分类数据添加到二级分类数据中！
                category2.put("categoryChild",categoryChild3);
            }
            //  将二级分类数据添加到一级对象中！
            category1.put("categoryChild",categoryChild2);

            //  将一级分类对象放入list 集合
            list.add(category1);
        }
        //  返回数据
        return list;
    }


    @Override
    public BaseTrademark getBaseTradeMark(Long tmId) {
        return baseTrademarkMapper.selectById(tmId);
    }
}
